<?php

class NewsModel extends Model
{
    /**
     * Количество новостей на 1 странице в админке
     *
     */
    const ADMIN_NEWS_ON_PAGE = 30;
    
    protected $table = 'news';
    
    /**
     * Количество найденных элементов последним запросом
     *
     * @var int
     */
    protected $total_count = 0;
    
    /**
     * Получить новость
     *
     * @param int $id
     * @param string $field
     * @return News
     */
    public function get($id, $field = 'id')
    {
        $row = $this->getQueryConstructor()->findById($id, $field)->fetch();
        
        return !empty($row) ? new News($row['id'], $row['title'], $row['hash'], $row['description'], $row['image'], $row['status'], $row['date'], $row['link'], $row['pubdate'], $row['rss_id'], $row['words_url']) : null;
    }
    
    /**
     * Удаляет запись о новости
     *
     * @param int $id
     * @return bool
     */
    public function delete($id)
    {
        return (bool)$this->exec('DELETE FROM `'.$this->table.'` WHERE id = '.intval($id));
    }
    
    /**
     * Добавляет новость
     *
     * @param News $news
     * @return int
     */
    public function add(News $news)
    {
        $data = array(
            'hash' => $news->getHash(),
            'link' => $news->getLink(),
            'status' => $news->getStatus(),
            'title' => $news->getTitle(),
            'description' => $news->getDescription(),
            'image' => $news->getImage(),
            'pubdate' => $news->getPubdate(),
            'rss_id' => $news->getRssId(),
            'words_url' => $news->getWordsUrl(),
            'words_url_hash' => $news->getWordsUrlHash(),
        );
        
        $sql = 'INSERT INTO `'.$this->table.'` (`hash`, `link`, `status`, `title`, `description`, `image`, `pubdate`, `rss_id`, `words_url`, `words_url_hash`) 
                VALUES (s:hash, s:link, i:status, s:title, s:description, s:image, s:pubdate, i:rss_id, s:words_url, s:words_url_hash)';
        return $this->prepare($sql)->query($data)->getInsertId();
    }
    
    /**
     * Обновляет новость
     *
     * @param News $news
     * @return bool
     */
    public function edit(News $news)
    {
        $set = array();
        if (!is_null($news->getTitle())) {
            $set[] = '`title` = s:title';
            $news->setWordsUrl(Utils::translateStr($news->getTitle()));
        }
        if (!is_null($news->getDescription())) {
            $set[] = '`description` = s:description';
        }
        if (!is_null($news->getStatus())) {
            $set[] = '`status` = i:status';
        }
        if (!is_null($news->getLink())) {
            $set[] = '`link` = s:link';
        }
        if ($news->getWordsUrl()) {
            $set[] = '`words_url` = s:words_url';
            $set[] = '`words_url_hash` = s:words_url_hash';
        }
        
        $data = array(
            'id' => $news->getId(),
            'title' => $news->getTitle(),
            'hash' => $news->getHash(),
            'description' => $news->getDescription(),
            'status' => $news->getStatus(),
            'image' => $news->getDate(),
            'link' => $news->getLink(),
            'pubdate' => $news->getPubdate(),
            'rss_id' => $news->getRssId(),
            'words_url' => $news->getWordsUrl(),
            'words_url_hash' => $news->getWordsUrlHash(),
        );
        
        if (!empty($set)) {
            $sql = 'UPDATE `'.$this->table.'` SET '.implode(', ', $set).' WHERE `id` = i:id';
            return (bool)$this->prepare($sql)->exec($data);
        }
        return false;
    }
    
    /**
     * Проверить существование новости по ее хешу
     *
     * @param string $hash
     * @return bool
     */
    public function issetByHash($hash)
    {
        return (bool)$this->getQueryConstructor()->findById($hash, 'hash')->fetch();
    }
    
    /**
     * @return int
     */
    public function getTotalCount()
    {
        return $this->total_count;
    }
    
    /**
     * Получить список новостей с заданным статусом
     *
     * @param int $page
     * @param int $limit
     * @param int $status
     * @return array(id => News)
     */
    public function getList($page = 0, $limit = self::ADMIN_NEWS_ON_PAGE, $status = null, $filter = array(), $order = array('field' => 'pubdate', 'by' => 'DESC'), $not_news = null)
    {
        $offset = (intval($page) > 0 ? intval($page) - 1 : 0) * $limit;
        
        if (!is_null($status)) {
            $c = $this->getQueryConstructor()->filter('status', $status);
        } else {
            $c = $this->getQueryConstructor();
        }
        
        foreach ((array)$filter as $field => $value) {
            $c->filter($field, $value);
        }
        
        if ($not_news) {
            $c->filter('id', $not_news, '!=');
        }
        
        $this->total_count = $c->count();
        $list = $c->order($order['field'], $order['by'])->limit($offset, $limit)->find()->fetchAll('id');

        $news_list = array();
        foreach ((array)$list as $id => $row) {
            $news_list[$id] = new News($row['id'], 
                                       $row['title'], 
                                       $row['hash'], 
                                       $row['description'], 
                                       $row['image'], 
                                       $row['status'], 
                                       $row['date'], 
                                       $row['link'], 
                                       $row['pubdate'], 
                                       $row['rss_id'],
                                       $row['words_url']);
        }
        
        return $news_list;
    }
    
    /**
     * Удаляет старые новости
     *
     */
    public function clearOldNews()
    {
        $this->query('DELETE FROM `'.$this->table.'` WHERE `pubdate` < CURDATE() - INTERVAL '.OLD_NEWS_DAYS.' DAY');
    }
    
    /**
     * Подсчитывает количество новостей для каждой rss-ленты
     *
     * @param unknown_type $rss_list
     * @return array
     */
    public function getCountByRss($rss_list = array(), $news_status = null)
    {
        $c = $this->getQueryConstructor()->fields(array('rss_id', 'COUNT(*) count'));
        
        if (!empty($rss_list)) {
            $c->filter('rss_id', $rss_list);
        }
        if (!is_null($news_status)) {
            $c->filter('status', $news_status);
        }
        
        $c->group('rss_id');
        
        return $c->find()->fetchAll('rss_id');
    }
}